using System.IO;
using Microsoft.SqlServer.Management.UI.VSIntegration;
using Microsoft.SqlServer.Management.UI.VSIntegration.ObjectExplorer;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Process = System.Diagnostics.Process;

namespace SsmsAddin
{
    public class Utils
    {
        private const string _CMD_COMMIT = "/command:commit /path:{0} /closeonend:0";
        private const string _CMD_LOCK = "/command:lock /path:{0} /closeonend:0";
        private const string _CMD_LOG = "/command:log /path:{0}";
        public static DBNode _DBNode;
        public const string _SVN_EXE = "TortoiseProc.exe";

        public static string ConcatUrls(string firstPart, string secondPart)
        {
            if (firstPart.EndsWith("/"))
            {
                    if (secondPart.StartsWith("/"))
                    {
                        firstPart = firstPart.TrimEnd('/');
                    }
                    return firstPart + secondPart;
            }
            if (secondPart.StartsWith("/"))
                return firstPart + secondPart;
            return firstPart + "/" + secondPart;
        }

        public static string _GetFilePath()
        {
            return _GetFilePath(_DBNode.objectType, _DBNode.objectName.ToLower());
        }

        public static string _GetFilePath(string ObjectType, string ObjectName)
        {
            return Path.Combine(GetLocalSvnPath(ObjectType), ObjectName.ToLower() + ".sql");

        }

        public static void execSvnCommand(svnCommand cmd)
        {
            var info = new ProcessStartInfo {
                FileName = "TortoiseProc.exe"
            };
            switch (cmd)
            {
                case svnCommand.scLog:
                    info.Arguments = getSvnCommand(svnCommand.scLog);
                    break;

                case svnCommand.scLock:
                    info.Arguments = getSvnCommand(svnCommand.scLock);
                    break;

                case svnCommand.scCommit:
                    info.Arguments = getSvnCommand(svnCommand.scCommit);
                    break;
            }
            Process process = new Process {
                StartInfo = info
            };
            process.Start();
            process.WaitForExit();
        }

        public static void execSvnCommand(svnCommand cmd, string file_path)
        {
            ProcessStartInfo info = new ProcessStartInfo {
                FileName = "TortoiseProc.exe"
            };
            switch (cmd)
            {
                case svnCommand.scLog:
                    info.Arguments = getSvnCommand(svnCommand.scLog, file_path);
                    break;

                case svnCommand.scLock:
                    info.Arguments = getSvnCommand(svnCommand.scLock, file_path);
                    break;

                case svnCommand.scCommit:
                    info.Arguments = getSvnCommand(svnCommand.scCommit, file_path);
                    break;
            }
            Process process = new Process {
                StartInfo = info
            };
            process.Start();
            process.WaitForExit();
        }

        private static string GetFormatedPath(string chemin)
        {
            return GetFormatedPath(chemin, _DBNode.objectType);
        }

        private static string GetFormatedPath(string chemin, string objectType)
        {
            chemin = chemin.Replace("{database}", _DBNode.dbName).Replace("{object}", objectType);
            return chemin;
        }

        public static string GetLocalSvnPath()
        {
            return GetFormatedPath(Properties.Settings.Default.LocalSvnPath);
        }

        public static string GetLocalSvnPath(string objectType)
        {
            return GetFormatedPath(Properties.Settings.Default.LocalSvnPath, objectType);
        }

        public static string GetServerSvnPath()
        {
            return GetFormatedPath(Properties.Settings.Default.ServerSvnPath);
        }

        public static string getSvnCommand(svnCommand cmd)
        {
            return getSvnCommand(cmd, _GetFilePath());
        }

        public static string getSvnCommand(svnCommand cmd, string FilePath)
        {
            string format = "";
            if (cmd == svnCommand.scLog)
            {
                format = "/command:log /path:{0}";
            }
            else if (cmd == svnCommand.scLock)
            {
                format = "/command:lock /path:{0} /closeonend:0";
            }
            else if (cmd == svnCommand.scCommit)
            {
                format = "/command:commit /path:{0} /closeonend:0";
            }
            return string.Format(format, FilePath);
        }

        public static void openCurrentObject()
        {
            openCurrentObject(_GetFilePath());
        }

        public static void openCurrentObject(string FilePath)
        {
            Process.Start(FilePath);
        }

        public static void UpdateObjectExplorerInfo()
        {
            INodeInformation[] informationArray;
            int num;
            ServiceCache.GetObjectExplorer().GetSelectedNodes(out num, out informationArray);
            INodeInformation information = (num > 0) ? informationArray[0] : null;
            if (information != null)
            {
                Regex regex2;
                ConnectionString = information.Connection.ConnectionString;
                _DBNode.objectType = null;
                _DBNode.objectName = null;
                Match match = new Regex(@"^Server\[@Name='(?<Server>[^']*)'\]/Database\[@Name='(?<Database>[^']*)'\]*").Match(information.Context);
                if (match.Groups.Count == 3)
                {
                    _DBNode.serverName = information.Connection.ServerName;
                    _DBNode.dbName = match.Groups["Database"].Value;
                }
                if (Regex.IsMatch(information.Context, "Trigger"))
                {
                    regex2 = new Regex(@"^Server\[@Name='(?<Server>[^']*)'\]/Database\[@Name='(?<Database>[^']*)'\]/Table\[@Name='(?:[^']*)' and @Schema='(?:[^']*)'\]/(?<ObjectType>[^']*)\[@Name='(?<ObjectName>[^']*)'\]$");
                }
                else
                {
                    regex2 = new Regex(@"^Server\[@Name='(?<Server>[^']*)'\]/Database\[@Name='(?<Database>[^']*)'\]/(?<ObjectType>(UserDefinedFunction|View|StoredProcedure|Table))\[@Name='(?<ObjectName>[^']*)' and @Schema='(?<Schema>[^']*)'\]$");
                }
                Match match2 = regex2.Match(information.Context);
                if ((match2 != null) && (match2.Groups.Count >= 4))
                {
                    _DBNode.objectType = match2.Groups["ObjectType"].Value;
                    _DBNode.objectName = match2.Groups["ObjectName"].Value;
                }
            }
        }

        public static string ConnectionString { get; private set; }

        [StructLayout(LayoutKind.Sequential)]
        public struct DBNode
        {
            public string dbName;
            public string objectName;
            public string objectType;
            public string serverName;
            public DBNode(string _serverName, string _dbName, string _objectType, string _objectName)
            {
                this.serverName = _serverName;
                this.dbName = _dbName;
                this.objectType = _objectType;
                this.objectName = _objectName;
            }
        }

        public enum svnCommand
        {
            scLog,
            scLock,
            scCommit
        }

        internal enum svnPath
        {
            spLocal,
            spServer
        }
    }
}
